
import pygame
import random


class Tetris():
    def __init__(self):
        # 设置游戏初始化
        pygame.init()
        # 设置最小尺寸
        self.size = 30
        # 设置游戏区域宽度数量
        self.width = 10
        # 设置高度数量
        self.height = 20
        # 是否循环
        self.is_loop = True
        # 是否结束
        self.is_end = False
        # 设置背景颜色
        self.bg_color = (189, 183, 107)
        # 设置网格线颜色
        self.line_color = (154, 205, 50)
        # 设置方块颜色
        self.block_color = (255, 69, 0)
        # 落到底部后的颜色
        self.game_area_color = (0, 255, 0)
        # 设置字体和字号
        self.font1 = pygame.font.SysFont('Simhei', 18)
        # 设置字体颜色
        self.font_color = (255, 106, 106)
        # 等级关卡
        self.level = 1
        # 得分
        self.score = 0
        #  blocks记录方块形状。
        self.blocks = []
        # 当前方块形状
        self.cur_block = None
        # 下一个的方块形状r
        self.next_block = None
        # 第一次出现的(x,y)的位置
        self.cur_block_lt = [4, -2]
        # 下一个方块形状的位置
        self.next_block_lt = [11, 7]
        # 下落速度
        self.speed = 0.05
        # self.level_speed = 0.05
        # 游戏区域
        self.game_area = []
        for i in range(self.height):
            row = []
            for j in range(self.width):
                row.append('.')
            self.game_area.append(row)

    def start(self):
        # 设置窗口大小
        self.screen = pygame.display.set_mode((self.size*(self.width+5), self.size*self.height))
        # 设置标题
        pygame.display.set_caption('俄罗斯方块')
        self.read_file()
        self.cur_block = self.get_block()
        self.next_block = self.get_block()
        clock = pygame.time.Clock()

        while self.is_loop:
            self.screen.fill(self.bg_color)
            self.event_handler()
            self.draw_grid()
            self.draw_text()
            self.draw_game_area()
            self.draw_block(self.cur_block, self.cur_block_lt)
            self.draw_block(self.next_block, self.next_block_lt)
            self.move()
            # 更新屏幕
            pygame.display.update()
            clock.tick(40)

        self.quit()

    def event_handler(self):
        """事件处理助手"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.is_loop = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x_list, y_list, pos_list = self.get_block_many_pos()
                    # 获取最小的元素是否到达边界
                    game_area_list = self.get_game_area_many_pos()
                    # 获取y列表最大的元素
                    # 是否停靠
                    is_stop = False
                    # 判断当前的block的下一个落点是否与game_area区域重合，
                    for pos in pos_list:
                        pos[0] -= 1
                        if pos in game_area_list:
                            is_stop = True
                            break
                    if min(x_list) != 0 and not is_stop:
                        self.cur_block_lt[0] -= 1
                elif event.key == pygame.K_RIGHT:
                    # 获取最大的元素是否到达边界
                    x_list, y_list, pos_list = self.get_block_many_pos()
                    # 获取最小的元素是否到达边界
                    game_area_list = self.get_game_area_many_pos()
                    # 获取y列表最大的元素
                    # 是否停靠
                    is_stop = False
                    # 判断当前的block的下一个落点是否与game_area区域重合，
                    for pos in pos_list:
                        pos[0] += 1
                        if pos in game_area_list:
                            is_stop = True
                            break
                    if max(x_list) != self.width-1 and not is_stop:
                        self.cur_block_lt[0] += 1
                elif event.key == pygame.K_DOWN:
                    self.cur_block_lt[1] += 0.5
                elif event.key == pygame.K_UP:
                    pass

    def draw_grid(self):
        """绘制游戏区域网格线"""
        for i in range(self.height+1):
            # 绘制线段
            pygame.draw.line(self.screen, self.line_color, (1, i*self.size), (self.width*self.size, i*self.size),2)
        for i in range(self.width+1):
            # 绘制线段
            pygame.draw.line(self.screen, self.line_color, (i*self.size, 0), (i*self.size, self.height*self.size), 2)

    def draw_text(self):
        """
        绘制文本信息，如关卡得分，下一个
        :return:
        """
        level_img = self.font1.render(
            f'关卡: {self.level}', True , self.font_color )
        self.screen.blit(level_img, (self.size*(self.width+1), self.size*2))
        score_img = self.font1.render(
            f'得分: {self.score}', True, self.font_color)
        self.screen.blit(score_img, (self.size * (self.width + 1), self.size * 4))

        next_img = self.font1.render(
            f'下一个:', True, self.font_color)
        self.screen.blit(next_img, (self.size * (self.width + 1), self.size * 6))


    def read_file(self):
        """读取配置文件"""
        with open('./elsfk.cfg', 'r') as file:
            self.blocks = file.readlines()

    def get_block(self):
        """获取一个方块形状"""
        # return self.blocks[4].strip()   #测试使用
        return random.choice(self.blocks).strip()

    def draw_block(self, block, pos):
        """
        绘制方块形状，将所有是1的元素绘制小的矩形
        :param block: 方块形状
        :param pos:  位置
        :return:
        """
        x, y = pos
        for i, v in enumerate(block):
            if v == '1':
                # 或者矩形区域
                pygame.draw.rect(self.screen, self.block_color, ((x+i % 5)*self.size, (y+i//5)*self.size ,self.size, self.size))

    def draw_game_area(self):
        """
        绘制整体游戏区域已经存放的方块
        :return:
        """
        for i, row in enumerate(self.game_area):
            for j, v in enumerate(row):
                if v == '1':
                    pygame.draw.rect(self.screen, self.game_area_color,
                                     (j * self.size, i * self.size, self.size, self.size))
    def update_game_area(self):
        x, y = self.cur_block_lt
        print('aaaaaa', self.game_area)
        for i, v in enumerate(self.cur_block):
            if v == '1':
                self.game_area[round((y + i // 5))][round(x+i%5)] = '1'

        for i, lst in enumerate(self.game_area):
            if '.' not in lst:
                # 移除填满的全是1的这一行
                self.game_area.pop(i)
                # 天加空列
                self.game_area.insert(0, [ '.' for a in range(self.width)])
                # 计算分数
                self.score += 1
                if self.score % 10 == 0:
                    self.level += 1
                    self.speed += 0.05
        print(self.game_area)



    def move(self):
        """block方块形状移动"""
        x_list, y_list, pos_list = self.get_block_many_pos()
        game_area_list = self.get_game_area_many_pos()
        # 获取y列表最大的元素
        max_y = max(y_list)

        # 是否停靠
        is_stop = False
        # 判断当前的block的下一个落点是否与game_area区域重合，
        for pos in pos_list:
            pos[1] += 1
            if pos in game_area_list:
                if  min(y_list) < 0:
                    print(self.cur_block_lt)
                    self.is_end = True
                else:
                    is_stop = True
                break
        if self.is_end:
            print('Game Over')
            self.restart()

        else:
            # 判断是否到达底部边界，和是否停靠
            if round(max_y) == self.height-1 or is_stop:
                self.update_game_area()
                # 将当前形状定死，换成下一个，并将提示的新生成一个
                self.cur_block = self.next_block
                self.cur_block_lt = [4, -2]
                self.next_block = self.get_block()
            else:
                self.cur_block_lt[1] += self.speed
        # self.speed = self.level_speed

    def get_block_many_pos(self):
        """获取block中为1的x列表， y列表， 坐标列表"""
        x_list, y_list, pos_list = [], [], []
        x, y = self.cur_block_lt
        for i, v in enumerate(self.cur_block):
            if v == '1':
                x_list.append(x + i % 5)
                y_list.append(round(y) + i // 5)
                pos_list.append([x + i % 5, round(y) + i // 5])
        return x_list, y_list, pos_list

    def get_game_area_many_pos(self):
        """获取游戏区域中为1的坐标列表"""
        pos_list = []
        for i, row in enumerate(self.game_area):
            for j, v in enumerate(row):
                if v == '1':
                    pos_list.append([j, i])
        return pos_list

    def restart(self):
        self.score = 0
        self.level = 0
        self.speed == 0.05
        self.cur_block_lt = [4, -2]
        self.cur_block = self.get_block()
        self.next_block = self.get_block()
        # 游戏区域
        self.game_area = []
        for i in range(self.height):
            row = []
            for j in range(self.width):
                row.append('.')
            self.game_area.append(row)
    def quit(self):
        """退出游戏"""
        pygame.display.quit()


if __name__ == '__main__':
    t = Tetris()
    t.start()
